'''
Created on 17.7.2011

@author: gilead
'''
from direct.showbase import DirectObject

from direct.task import Task

from panda3d.core import Point3,Plane,Vec3,Vec4 #@UnresolvedImport
from panda3d.core import CollisionTraverser,CollisionNode,CollisionPlane #@UnresolvedImport
from panda3d.core import CollisionHandlerQueue,CollisionRay #@UnresolvedImport

from SingleLine import SingleLine

class MouseHandler(DirectObject.DirectObject):
    '''
    classdocs
    '''
    def __init__(self, render, camera, camManager, taskMgr, server, world):
        '''
        Constructor
        '''
        self.server = server
        self.world = world
        
        self.camManager = camManager
        
        self.oldMouseX = 0
        self.oldMouseY = 0
        
        self.accept('wheel_up', self.WheelUp)
        self.accept('wheel_down', self.WheelDown)
        self.accept('mouse3', self.Mouse2Down)
        self.accept('mouse3-up', self.Mouse2Up)
        self.accept('mouse1', self.Mouse1Down)
        
        # onko hiiren nappi pohjassa?
        self.MouseDragging = False
        
        # tahan talletetaan hiiren sijainti, joka mahdollistaa kuvakulman vaihtamisen hiirella raahaamalla
        self.oldMouseX = 0
        self.oldMouseY = 0
        
        taskMgr.add(self.MouseUpdateTask, "MouseUpdateTask")
        
        self.picker = CollisionTraverser()            #Make a traverser
        self.pq     = CollisionHandlerQueue()         #Make a handler
        
        self.pickerNode = CollisionNode('mouseRay')
        #Attach that node to the camera since the ray will need to be positioned
        #relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        self.pickerRay = CollisionRay()               #Make our ray
        self.pickerNode.addSolid(self.pickerRay)      #Add it to the collision node
        #Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)
        
        # A Line that points from selected ship to where-ever the mouse is
        self.pointingLine = SingleLine(render, 2.0, Vec4(0,0,255,1))
        
        cNode = CollisionNode("xyplane")
        plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
        cNode.addSolid(plane)
        self.xyplane = render.attachNewNode(cNode)
        #self.xyplane.show()
    
    def GetMousePosOnPlane(self):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            self.picker.traverse(self.xyplane)
            if self.pq.getNumEntries() > 0:
                pos = self.pq.getEntry(0).getSurfacePoint(self.xyplane)
                return pos
        else:
            return None
    
    def Mouse2Down(self):
        self.MouseDragging = True
        self.pointingLine.hide()
        #print self.oldMouseX, self.oldMouseY, base.mouseWatcherNode.getMouse()
        #self.oldMousePOS = base.mouseWatcherNode.getMouse()
        self.oldMouseX = base.mouseWatcherNode.getMouse().getX()
        self.oldMouseY = base.mouseWatcherNode.getMouse().getY()
        
    def Mouse2Up(self):
        self.MouseDragging = False
        self.pointingLine.show()
    
            
    def MouseUpdateTask(self, task):
        if self.MouseDragging:
            if base.mouseWatcherNode.hasMouse():
                mpos = base.mouseWatcherNode.getMouse() # get the mouse position
                diffX = self.oldMouseX - mpos.getX()
                diffY = self.oldMouseY - mpos.getY()
                #print mpos, self.oldMousePOS
                self.camManager.SpinCameraX(diffX)
                self.camManager.SpinCameraZ(diffY)
                self.oldMouseX = mpos.getX();
                self.oldMouseY = mpos.getY();
        else:
            # piirretaan viiva
            mpos = self.GetMousePosOnPlane()
            if mpos != None:
                if self.camManager.focusShip != None:
                    pos = self.camManager.focusShip.getPos()
                    min, max = self.camManager.focusShip.getTightBounds()
                    #med = (max + min) / 2
                    #print pos,med
                    #pos += med
                    self.pointingLine.redraw(mpos.getX(), mpos.getY(), mpos.getZ(), 
                                             pos.getX(),  pos.getY(),  pos.getZ())
            else:
                self.pointingLine.hide()
                    #print pos, mpos
        # periaatteessa kameran paikkaa ei tarvitsisi laskea ennenkuin havaittaisiin, etta kameran kohde olisi liikkunut
        self.camManager.PositionCamera()
        return Task.cont
    
    def WheelUp(self):
        self.camManager.ZoomIn()
        
    def WheelDown(self):
        self.camManager.ZoomOut()
        
    def setFocusShip(self, ship):
        # asetetaan tulitusarkkien nakyvyys oikein.. ts. vaihdetaan ne paittain
        otherArcStatus = False
        
        for shipchild in ship.getChildren():
            turret = shipchild.getPythonTag('Turret')
            if turret != None:
                for turretchild in turret.getChildren():
                    if turretchild.node().isGeomNode():
                        otherArcStatus = turretchild.isHidden()
                        break
        
        focusShipArcStatus = False
        for shipchild in self.camManager.focusShip.getChildren():
            turret = shipchild.getPythonTag('Turret')
            if turret != None:
                for turretchild in turret.getChildren():
                    if turretchild.node().isGeomNode():
                        focusShipArcStatus = turretchild.isHidden()
                        if otherArcStatus:
                            turretchild.hide()
                        else:
                            turretchild.show()
                        
        for shipchild in ship.getChildren():
            turret = shipchild.getPythonTag('Turret')
            if turret != None:
                for turretchild in turret.getChildren():
                    if turretchild.node().isGeomNode():
                        if focusShipArcStatus:
                            turretchild.hide()
                        else:
                            turretchild.show()
         
        self.camManager.focusShip = ship
        
    def Mouse1Down(self):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
         
            self.picker.traverse(self.world)
            # Assume for simplicity's sake that myHandler is a CollisionHandlerQueue.
            if self.pq.getNumEntries() > 0:
                # This is so we get the closest object.
                self.pq.sortEntries()
                pickedObj = self.pq.getEntry(0).getIntoNodePath()
                #getIntoNodePath palauttaa CollisionNode:n, joka on kiinnitetty actorin lapseksi
                pickedObj = pickedObj.findNetTag('selectableObject')
                #findNetTag palauttaa alhaisimman esi-isan jolla on haluttu tagi
                if not pickedObj.isEmpty():
                    ship = pickedObj.getPythonTag('Ship')
                    if ship != None:
                        if ship.ownerid == self.world.userID:
                            self.setFocusShip(ship)
                        else:
                            print "clicked someone else's ship! ", ship.ownerid, " vs ", self.world.userID 
            else:
                self.picker.traverse(self.xyplane)
                if self.pq.getNumEntries() > 0:
                    pos = self.pq.getEntry(0).getSurfacePoint(self.xyplane)
                    # asetetaan piste valitun aluksen matkakohteeksi
                    if self.camManager.focusShip != None:
                        self.server.SendMoveOrder(self.camManager.focusShip.guid, pos.getX(), pos.getY())
                    self.camManager.focusShip.setMovementTarget(pos)